package com.xcity.pomelo.response;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import com.alibaba.fastjson.annotation.JSONField;
import com.xcity.db.entity.Player;
import com.xcity.game.combat.attr.CombatAttributeType;
import com.xcity.game.common.ConfirmOperation;
import com.xcity.game.equip.Equip;
import com.xcity.game.equip.Equip.State;
import com.xcity.game.equip.EquipBrand;
import com.xcity.game.equip.EquipPosition;
import com.xcity.game.equip.EquipQuality;
import com.xcity.game.equip.EquipSuit;
import com.xcity.game.equip.EquipUtils;
import com.xcity.game.equip.template.EquipSuitEffectTemplate;

import naga.x.App;
import naga.x.game.template.TemplateService;
import naga.x.net.impl.pomelo.PomeloMessage;
import naga.x.net.impl.pomelo.protocol.Message;

@PomeloMessage(type = Message.Type.RESPONSE)
public class EquipmentBagResponse extends Response {
	
	protected List<Equipment> equips;
	
	public static class Equipment extends Equip {
		private Equip ref;
		private List<CombatAttribute> attrs0;
		private List<com.xcity.game.combat.attr.CombatAttribute> next = Collections.emptyList();
		public static final Equipment EMPTY = new Equipment();
		private Equipment() {
			attrs = Collections.emptyList();
		}
		public Equipment(Equip ref) {
			this.ref = ref;
			this.attrs0 = new ArrayList<CombatAttribute>(ref.getAttrs().size());
			for (int i = 0; i < ref.getAttrs().size(); i++) {
				this.attrs0.add(new CombatAttribute(ref.getAttrs().get(i)));
			}
			setAttrs(ref.getAttrs());
			this.next = EquipUtils.getNextLevelAttrs(this);
		}
		@JSONField(name = "id")
		public long getId() {
			return ref != null ? ref.getId() : 0L;
		}
		public String getName() {
			return ref != null ? ref.getTemplate().getName() : null;
		}
		public String getDesc() {
			return null;
		}
		public String getIcon() {
			return ref != null ? ref.getTemplate().getIcon() : null;
		}
		@JSONField(name = "level")
		public int getLevel() {
			return ref != null ? ref.getLevel() : 0;
		}
		@Override
		public EquipQuality getQuality() {
			return ref != null ? ref.getDataTemplate().getQuality() : null;
		}
		@Override
		public EquipPosition getPos() {
			return ref != null ? ref.getTemplate().getPos() : null;
		}
		@JSONField(name = "exp")
		public int getExp() {
			return ref != null ? EquipUtils.getCurrentExp(getQuality(), ref.getExp(), getLevel()) : 0;
		}
		public int getExp0() {
			return ref != null ? ref.getExp() : 0;
		}
		public int getMaxExp() {
			return ref != null ? EquipUtils.getNextLvlNeedExp(getQuality(), getLevel()) : 0;
		}
		@JSONField(name = "attrs")
		public List<CombatAttribute> getAttrs0() {
			return attrs0;
		}
		@JSONField(serialize = false)
		@Override
		public int getTemplateId() {
			return ref != null ? ref.getTemplateId() : 0;
		}
		@JSONField(serialize = false)
		@Override
		public int getDataTemplateId() {
			return ref != null ? ref.getDataTemplateId() : 0;
		}
		@JSONField(serialize = false)
		@Override
		public List<com.xcity.game.combat.attr.CombatAttribute> getAttrs() {
			return ref != null ? ref.getAttrs() : null;
		}
		@JSONField(serialize = false)
		@Override
		public State getState() {
			return ref != null ? ref.getState() : null;
		}
		@JSONField(serialize = false)
		@Override
		public long getCreateTime() {
			return ref != null ? ref.getCreateTime() : 0L;
		}
		@Override
		public EquipBrand getBrand() {
			return ref != null ? ref.getTemplate().getBrand() : null;
		}
		@JSONField(serialize = false)
		@Override
		public boolean isEmpty() {
			return ref == null || ref.isEmpty();
		}
		public List<com.xcity.game.combat.attr.CombatAttribute> getNext() {
			return next;
		}
	}
	
	public static class EquipmentSuit {
		public EquipBrand brand;
		public String icon;
		public List<EquipmentSuitEffect> effects;
		public EquipmentSuit(EquipSuitEffectTemplate template) {
			this.brand = template.getBrand();
			this.icon = template.getIcon();
			this.effects = new ArrayList<>(2);
			this.effects.add(new EquipmentSuitEffect(ConfirmOperation.NO, EquipSuit.SUIT2, template));
			this.effects.add(new EquipmentSuitEffect(ConfirmOperation.NO, EquipSuit.SUIT4, template));
		}
		
		public EquipmentSuitEffect getEffect(byte type) {
			for (int i = 0; i < effects.size(); i++) {
				EquipmentSuitEffect eff = effects.get(i);
				if (eff.type == type) {
					return eff;
				}
			}
			return null;
		}
		
		public static EquipmentSuitEffect find(List<EquipmentSuit> suits, EquipBrand brand, EquipSuit type) {
			EquipmentSuit found = null;
			for (int i = 0; i < suits.size(); i++) {
				EquipmentSuit suit = suits.get(i);
				if (suit.brand == brand) {
					found = suit;
					break;
				}
			}
			if (found == null) {
				EquipSuitEffectTemplate effTemp = App.getApp().getServiceManager().get(TemplateService.class).get(EquipSuitEffectTemplate.class, brand.ordinal());
				suits.add(found = new EquipmentSuit(effTemp));
			}
			return found.getEffect(type.type);
		}
	}
	
	public static class EquipmentSuitEffect {
		public byte active; // 套装效果是否激活
		public byte type; // 2: 2件套效果, 4: 4件套效果
		public String desc; // 效果描述
		@JSONField(serialize = false)
		public EquipSuitEffectTemplate template;
		public EquipmentSuitEffect(byte active, EquipSuit suit, EquipSuitEffectTemplate template) {
			this.active = active;
			this.type = suit.type;
			this.desc = suit == EquipSuit.SUIT2 ? template.getSuit2() : template.getSuit4();
			this.template = template;
		}
		public com.xcity.game.combat.attr.CombatAttribute getEnhancedAttribute(CombatAttributeType attrType) {
			if (active != ConfirmOperation.YES) {
				return null;
			}
			return template.getEnhancedAttribute(EquipSuit.forType(type), attrType);
		}
	}
	
	public static class CombatAttribute extends com.xcity.game.combat.attr.CombatAttribute {
		private float factor;
		private com.xcity.game.combat.attr.CombatAttribute refer;
		public CombatAttribute(com.xcity.game.combat.attr.CombatAttribute refer) {
			this(refer, 1f);
		}
		public CombatAttribute(com.xcity.game.combat.attr.CombatAttribute refer, float factor) {
			this.factor = factor;
			this.refer = refer;
		}
		@JSONField(name = "type")
		public CombatAttributeType getType() {
			return refer.getType();
		}
		@JSONField(name = "value")
		public Object getValue0() {
			return format(getValue());
		}
		@JSONField(serialize = false)
		@Override
		public float getValue() {
			return refer.getValue() * factor;
		}
		@Override
		public float doFilter(float value, float factor) {
			return refer.doFilter(value, factor);
		}
		@Override
		public Object format(float value) {
			return refer.format(value);
		}
	}
	
	public EquipmentBagResponse(int serial, Player player) {
		super(serial);
		List<Equip> list = player.getEquips().getEquipments();
		this.equips = new ArrayList<Equipment>(list.size());
		for (int i = 0; i < list.size(); i++) {
			Equip ref = list.get(i);
			if (ref.getState() == State.IN_BAG) {
				this.equips.add(new Equipment(ref));
			}
		}
	}

	public List<Equipment> getEquips() {
		return equips;
	}

	public void setEquips(List<Equipment> equips) {
		this.equips = equips;
	}

}
